﻿#define _CRT_SECURE_NO_WARNINGS

//38.
//反转 ⼀个整数意味着倒置它的所有位。
//例如，反转 2021 得到 1202 。反转 12300 得到 321 ，不保留前导零 。
//给你⼀个整数 num ，反转 num 得到 reversed1 ，接着反转 reversed1 得到 reversed2
//。如果 reversed2 等于 num ，返回 true ；否则，返回 false 。

bool isSameAfterReversals(int num) {
    return num == 0 || num % 10 != 0;
}

//39.
//给你⼀个整数数组 nums ，返回数组中最⼤数和最⼩数的 最⼤公约数 。
//两个数的 最⼤公约数 是能够被两个数整除的最⼤正整数。
int findGCD(int* nums, int numsSize) {
    // 获取最大值和最小值
    int max = nums[0];
    int min = nums[0];
    int i;
    for (i = 1; i < numsSize; i++) {
        if (nums[i] > max)
            max = nums[i];
        if (nums[i] < min)
            min = nums[i];
    }
    // 求最大公约数
    int m;
    for (m = min; m >= 1; m--) {
        if (max % m == 0 && min % m == 0)
            break;
    }
    return m;
}

//40.
//给你⼀个整数数组 nums ，请你返回其中位数为 偶数 的数字的个数。
int findNumbers(int* nums, int numsSize) {
    int count;
    int num = 0;
    int i;
    for (i = 0; i < numsSize; i++) {
        count = 0;
        while (nums[i]) {
            nums[i] /= 10;
            count++;
        }
        if (count % 2 == 0)
            num++;
    }
    return num;
}

//41.
//给你一个正整数数组 nums ，请你返回一个数组 answer ，你需要将 nums 中每个整数进行数位分割后，按照 nums 中出现的 相同顺序 放入答案数组中。
//对一个整数进行数位分割，指的是将整数各个数位按原本出现的顺序排列成数组。
//比方说，整数 10921 ，分割它的各个数位得到[1, 0, 9, 2, 1] 。

//方法一 超级暴力求解
int* separateDigits(int* nums, int numsSize, int* returnSize) {
    int i;
    int temp[numsSize];
    for (i = 0; i < numsSize; i++)
        temp[i] = nums[i];

    int count = 0;
    int index[numsSize];
    int a;
    for (i = 0; i < numsSize; i++) {
        a = 0;
        while (temp[i]) {
            count++;
            a++;
            temp[i] /= 10;
        }
        index[i] = a;
    }
    int size = count;
    int j = 0;
    int* answer = (int*)malloc(sizeof(int) * count);
    for (i = 0; i < numsSize; i++) {
        while (nums[i]) {
            answer[j] = nums[i] % 10;
            nums[i] /= 10;
            j++;
        }
        // 反转answer
        int left = j - index[i];
        int right = j - 1;
        while (left < right) {
            int temp = answer[left];
            answer[left] = answer[right];
            answer[right] = temp;
            left++;
            right--;
        }

    }

    *returnSize = size;
    return answer;
}


//42.
//小扣在秋日市集发现了一款速算机器人。店家对机器人说出两个数字（记作 x 和 y），请小扣说出计算指令：
//"A" 运算：使 x = 2 * x + y；
//"B" 运算：使 y = 2 * y + x。
//在本次游戏中，店家说出的数字为 x = 1 和 y = 0，
//小扣说出的计算指令记作仅由大写字母 A、B 组成的字符串 s，字符串中字符的顺序表示计算顺序，
//请返回最终 x 与 y 的和为多少。
int calculate(char* s) {
    int len = strlen(s);
    int i;
    int x = 1;
    int y = 0;

    //分别取出每一个字符
    for (i = 0; i < len; i++)
    {
        char temp = s[i];
        //字符为A
        if (temp == 'A')
        {
            x = 2 * x + y;
        }
        //字符为B
        else
        {
            y = 2 * y + x;
        }
    }
    return x + y;
}

//43.
//给你一个字符串 s ，将该字符串中的大写字母转换成相同的小写字母，返回新的字符串。
char* toLowerCase(char* s) {
    int len = strlen(s);
    int i;
    for (i = 0; i < len; i++) {
        if (s[i] >= 'A' && s[i] <= 'Z') {
            s[i] = (char)(s[i] + 32);
        }
    }
    return s;
}

//44.
//给你一个正整数 n ，找出满足下述条件的 中枢整数 x ：
//1 和 x 之间的所有元素之和等于 x 和 n 之间所有元素之和。
//返回中枢整数 x 。如果不存在中枢整数，则返回 - 1 。题目保证对于给定的输入，至多存在一个中枢整数。
int pivotInteger(int n) {
    int i;
    int j;
    for (i = 1; i <= n; i++)
    {
        j = 1;
        int sum1 = 0;
        int sum2 = 0;
        while (j <= i)
        {
            sum1 = sum1 + j;//1
            j++;//2
        }
        int m = j - 1;//m=1
        while (m <= n)
        {
            sum2 = sum2 + m;//1
            m++;//2
        }
        if (sum1 == sum2)
        {
            return j - 1;
        }
    }
    return -1;
}

//方法二：等差数列求和比价
int pivotInteger(int n) {
    int i;
    for (i = 1; i <= n; i++) {
        if ((1 + i) * i / 2 == ((i + n) * (n - i + 1) / 2))
            return i;
    }
    return -1;
}

//方法三 根据公式推算
int pivotInteger(int n) {
    int x = sqrt(n * (1 + n) / 2);
    if ((1 + x) * x / 2 == (x + n) * (n - x + 1) / 2)
        return x;
    return -1;
}

//45.
//给你两个正整数 a 和 b ，返回 a 和 b 的 公 因子的数目。
//如果 x 可以同时整除 a 和 b ，则认为 x 是 a 和 b 的一个 公因子 。
int commonFactors(int a, int b) {
    int min = a < b ? a : b;
    int i;
    int count;
    for (i = 1; i <= min; i++) {
        if (a % i == 0 & b % i == 0)
            count++;
    }
    return count;
}

//方法二：数学思想
int gcd(int a, int b)
return b == 0 ? a : gcd(b, a % b);
}

int commonFactors(int a, int b) {
    // 记m为a和b的最⼤公约数
    int m = gcd(a, b);//m=6
    // 记录a和b的公因⼦
    int cnt = 0;
    int i;
    // 以最⼤公约数的开⽅为上限，从1开始遍历，当i≤m的开⽅时，i*i≤m
    for (i = 1; i * i <= m; i++) { //i=1,2
        if (m % i == 0) {
            // x是m的因⼦，可以作为a和b的公因⼦
            cnt++;
            // 如果i*i!=m，则m/i（不与i相等）也可以作为m的因⼦，即a和b的公因⼦
            if (i * i != m)
                cnt++;
        }
    }
    // 返回公因⼦个数
    return cnt;
}

//46.
//存在⼀种仅⽀持 4 种操作和 1 个变量 X 的编程语⾔：
//++X 和 X++ 使变量 X 的值 加 1
//--X 和 X-- 使变量 X 的值 减 1
//最初， X 的值是 0
//给你⼀个字符串数组 operations ，这是由操作组成的⼀个列表，返回执⾏所有操作后， X 的 最
//终值 。
int finalValueAfterOperations(char** operations, int operationsSize) {
    int i;
    int j;
    int x = 0;
    // 获取每一行操作符
    for (i = 0; i < operationsSize; i++) {
        // 获取每一行中第二个符号 第二个要么是+要么是-
        if (operations[i][1] == '+')
            x++;
        else
            x--;
    }
    return x;
}